from fastapi import Request, Response
from fastapiApp.models.admin import AuditLog_Mo, User_Mo
from fastapiApp.controllers.user_control import get_username_token, GL_DependAuth
import time
import json
from fastapi import Request, Response

# 使用统一的日志配置
from fastapiApp.setting.logger_config import get_audit_logger

logger = get_audit_logger()

async def audit_log_middleware(request: Request, call_next):
    # 只记录非GET和非OPTIONS请求
    if request.method != "GET" and request.method != "OPTIONS":
        start_time = time.time()

        # 尝试从请求头获取token并解析用户名
        token = None
        # 1. 从Authorization头获取（支持Bearer格式）
        auth_header = request.headers.get("Authorization", "")
        if auth_header:
            if auth_header.startswith("Bearer "):
                token = auth_header[7:].strip()  # 移除'Bearer '前缀
            else:
                token = auth_header.strip()  # 如果没有Bearer前缀，直接使用

        # 2. 如果请求头中没有，尝试从查询参数获取
        if not token:
            token = request.query_params.get("token", "")

        # 3. 调试信息记录
        logger.debug(f"路径: {request.url.path}, 方法: {request.method}, 找到的token: {'存在' if token else '不存在'}")
        logger.debug(f"当前活跃token列表: {len(GL_DependAuth)} 个项目")

        # 获取用户名
        username = "none user"
        if token:
            try:
                username = get_username_token(token)
                if username:
                    logger.debug(f"成功从token获取用户名: {username}")
                else:
                    logger.debug("无法从token获取用户名，token可能已过期或无效")
                    username = "invalid_token"
            except Exception as e:
                logger.error(f"解析token时发生错误: {str(e)}")
        else:
            logger.debug("未提供token")

        # 确保username不为None
        username = username or "none user"

        # 获取请求参数
        try:
            if request.method in ["POST", "PUT", "PATCH"]:
                body = await request.body()
                request_args = json.loads(body.decode("utf-8")) if body else {}
            else:
                request_args = dict(request.query_params)
        except Exception:
            request_args = {}

        # 执行请求
        response = await call_next(request)

        # 计算响应时间
        response_time = int((time.time() - start_time) * 1000)

        # 获取响应体
        response_body = b""
        async for chunk in response.body_iterator:
            response_body += chunk

        # 重新构建响应
        response = Response(
            content=response_body,
            status_code=response.status_code,
            headers=dict(response.headers),
            media_type=response.media_type
        )

        # 解析响应体
        try:
            response_data = json.loads(response_body.decode("utf-8")) if response_body else {}
        except Exception:
            response_data = {}

        # 提取模块信息和摘要
        path_parts = request.url.path.split("/")
        # 正确获取v1后的那一级作为模块名，路径格式如：/api/v1/module/...
        module = path_parts[3] if len(path_parts) > 3 else "unknown"
        summary = f"{request.method} {request.url.path}"

        # 查询用户ID
        user_id = 0  # 默认值
        try:
            if username and username not in ["none user", "invalid_token"]:
                user = await User_Mo.filter(username=username).first()
                if user:
                    user_id = user.id
                    logger.debug(f"找到用户: {username}, ID: {user_id}")
                else:
                    logger.debug(f"未找到用户: {username}")
        except Exception as e:
            logger.error(f"查询用户信息时发生错误: {str(e)}")

        # 记录审计日志
        try:
            await AuditLog_Mo.create(
                user_id=user_id,  # 使用真实用户ID或默认值
                username=username,
                module=module,
                summary=summary,
                method=request.method,
                path=request.url.path,
                status=response.status_code,
                response_time=response_time,
                request_args=request_args,
                response_body=response_data
            )
            logger.debug(f"审计日志记录成功: {request.method} {request.url.path}, 用户: {username}")
        except Exception as e:
            logger.error(f"记录审计日志时发生错误: {str(e)}")

        return response

    # GET和OPTIONS请求直接通过
    return await call_next(request)
